﻿#region

using System;
using System.Linq;
using System.Web.Mvc;
using HouseHoldBudget.Core.Entities.Expenses;
using HouseHoldBudget.Models.Expenses;
using HouseHoldBudget.Services.Expenses;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;

#endregion

namespace HouseHoldBudget.Controllers
{
    public class ExpensesController : BudgetControllerBase
    {
        #region Readonly & Static Fields

        private readonly IExpenseService _expenseService;
        private readonly IExpenseTypesService _expenseTypesService;

        #endregion

        #region Constructors

        public ExpensesController(IExpenseService expenseService,
                                  IExpenseTypesService expenseTypesService)
        {
            _expenseService = expenseService;
            _expenseTypesService = expenseTypesService;
        }

        #endregion

        #region Instance Methods

        /// <summary>
        ///   Deletes one expense.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <param name="id"> The id. </param>
        /// <param name="listModel"> The list model. </param>
        /// <returns> </returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult DeleteExpense([DataSourceRequest] DataSourceRequest request, Guid id, ExpensesListModel listModel)
        {
            _expenseService.DeleteExpense(id);

            return GetAllExpensesAsJson(request, listModel);
        }

        /// <summary>
        ///   Deletes the type of the expense.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <param name="id"> The id. </param>
        /// <returns> </returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult DeleteExpenseType([DataSourceRequest] DataSourceRequest request, Guid id)
        {
            _expenseTypesService.DeleteExpenseTypes(id);

            return GetAllExpensesTypeAsJson(request);
        }

        /// <summary>
        ///   Gets all expense types.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <returns> </returns>
        public ActionResult GetExpenseTypes([DataSourceRequest] DataSourceRequest request)
        {
            return GetAllExpensesTypeAsJson(request);
        }

        /// <summary>
        ///   Gets the expenses list.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <param name="model"> The model. </param>
        /// <returns> </returns>
        public ActionResult GetExpensesList([DataSourceRequest] DataSourceRequest request, ExpensesListModel model)
        {
            return GetAllExpensesAsJson(request, model);
        }

        /// <summary>
        ///   Inserts one expense.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <param name="model"> The model. </param>
        /// <returns> </returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult InsertExpense([DataSourceRequest] DataSourceRequest request, ExpenseModel model)
        {
            //if (ModelState.IsValid)
            //{
                Expense expense = new Expense
                                      {
                                          Id = Guid.NewGuid(),
                                          ExpenseAmount = model.ExpenseAmount,
                                          ExpenseLabel = model.ExpenseLabel,
                                          BudgetUserId = CurrentBudgetUser.Id,
                                          ExpenseOn = model.ExpenseOn,
                                          ExpensesTypes = _expenseTypesService.GetExpenseTypeById(model.ExpenseType.Id),
                                      };

                _expenseService.InsertExpense(expense);

                model.Id = expense.Id;
                return Json(new[] {model}.ToDataSourceResult(request));
            //}

            //return RedirectToAction("ShowMyExpenses");
        }

        /// <summary>
        ///   Inserts the type of the expense.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <param name="model"> The model. </param>
        /// <returns> </returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult InsertExpenseType([DataSourceRequest] DataSourceRequest request, ExpenseTypesModel model)
        {
            //if (ModelState.IsValid)
            //{
                ExpenseType expenseType = new ExpenseType
                                              {
                                                  Id = Guid.NewGuid(),
                                                  ExpenseTypeName = model.ExpenseTypeName,
                                              };

                _expenseTypesService.InsertExpenseTypes(expenseType);

                model.Id = expenseType.Id;
                return Json(new[] {model}.ToDataSourceResult(request));
            //}

            //return RedirectToAction("ManageExpenseTypes");
        }

        /// <summary>
        ///   Manages the expense types.
        /// </summary>
        /// <returns> </returns>
        public ActionResult ManageExpenseTypes()
        {
            return View();
        }

        /// <summary>
        ///   Shows the expenses list view
        /// </summary>
        /// <returns> </returns>
        public ActionResult ShowMyExpenses()
        {
            //Get the list of expense types
            var categories = _expenseTypesService.GetAllExpenseTypes().Select(PrepareExpenseTypesForList);
            ViewData["expensesTypes"] = categories;
            ViewData["defaultexpensesTypes"] = categories.First();
            return View(GetAllExpenses());
        }

        /// <summary>
        /// Updates one expense.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="model">The model.</param>
        /// <param name="startDate">The start date.</param>
        /// <param name="endDate">The end date.</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult UpdateExpense([DataSourceRequest] DataSourceRequest request, ExpenseModel model, DateTime startDate, DateTime endDate)
        {
            //update Expense
            if (ModelState.IsValid)
            {
                Expense CurrentExpense = _expenseService.GetExpensesById(model.Id);
                CurrentExpense.ExpenseAmount = model.ExpenseAmount;
                CurrentExpense.ExpenseLabel = model.ExpenseLabel;
                CurrentExpense.ExpenseOn = model.ExpenseOn;

                //Set expense type
                CurrentExpense.ExpensesTypes = _expenseTypesService.GetExpenseTypeById(model.ExpenseType.Id);
                _expenseService.UpdateExpense(CurrentExpense);

                return Json(model);
            }

            return RedirectToAction("ShowMyExpenses");
        }

        /// <summary>
        ///   Updates the type of the expense.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <param name="model"> The model. </param>
        /// <returns> </returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult UpdateExpenseType([DataSourceRequest] DataSourceRequest request, ExpenseTypesModel model)
        {
            if (ModelState.IsValid)
            {
                ExpenseType CurrentExpense = _expenseTypesService.GetExpenseTypeById(model.Id);
                CurrentExpense.ExpenseTypeName = model.ExpenseTypeName;
                _expenseTypesService.UpdateExpenseTypes(CurrentExpense);

                return Json(model);
            }

            return RedirectToAction("ManageExpenseTypes");
        }

        /// <summary>
        ///   Gets all expenses.
        /// </summary>
        /// <returns> </returns>
        [NonAction]
        private ExpensesListModel GetAllExpenses()
        {
            ExpensesListModel model = new ExpensesListModel
                                          {
                                              StartDateFilter = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1),
                                              EndDateFilter = DateTime.Now,
                                          };
            return model;
        }

        /// <summary>
        ///   Gets all expenses as json.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <param name="listModel"> The list model. </param>
        /// <returns> </returns>
        [NonAction]
        private JsonResult GetAllExpensesAsJson([DataSourceRequest] DataSourceRequest request, ExpensesListModel listModel)
        {
            var expenses = _expenseService.GetExpensesByUserId(CurrentBudgetUser.Id, listModel.StartDateFilter, listModel.EndDateFilter);
            return Json(expenses.Select(PrepareExpenseModelForList).ToDataSourceResult(request, ModelState));
        }

        /// <summary>
        ///   Gets all expenses type as json.
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <returns> </returns>
        [NonAction]
        private JsonResult GetAllExpensesTypeAsJson([DataSourceRequest] DataSourceRequest request)
        {
            var ex = _expenseTypesService.GetAllExpenseTypes();
            return Json(ex.Select(PrepareExpenseTypesForList).ToDataSourceResult(request, ModelState));
        }

        /// <summary>
        ///   Prepares the customer model for list.
        /// </summary>
        /// <param name="expense"> The expense. </param>
        /// <returns> </returns>
        [NonAction]
        private ExpenseModel PrepareExpenseModelForList(Expense expense)
        {
            var model = new ExpenseModel
                            {
                                ExpenseAmount = expense.ExpenseAmount,
                                ExpenseLabel = expense.ExpenseLabel,
                                Id = expense.Id,
                                ExpenseOn = expense.ExpenseOn,
                            };

            //Get type
            var expenseTypeId = _expenseTypesService.GetExpenseTypeById(expense.ExpensesTypeId.Value);
            model.ExpenseType = new ExpenseTypesModel
                                    {
                                        Id = expenseTypeId.Id,
                                        ExpenseTypeName = expenseTypeId.ExpenseTypeName,
                                    };

            return model;
        }

        /// <summary>
        ///   Prepares the expense types for list.
        /// </summary>
        /// <param name="expense"> The expense. </param>
        /// <returns> </returns>
        [NonAction]
        private ExpenseTypesModel PrepareExpenseTypesForList(ExpenseType expense)
        {
            return new ExpenseTypesModel
                       {
                           Id = expense.Id,
                           ExpenseTypeName = expense.ExpenseTypeName,
                       };
        }

        #endregion
    }
}